From 8c364f217ac999ed0bb80cafa86a77f4c79a9d6b Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 27 Feb 2007 13:43:01 +0000 Subject: [PATCH] linux: Don't allow partial message raeds from xenstore across save/restore. This patch is an essential companion to 13519:b4a8000e76db6b4b27341. Signed-off-by: Keir Fraser --- .../drivers/xen/xenbus/xenbus_comms.c | 12 ++++-- .../drivers/xen/xenbus/xenbus_comms.h | 1 + .../drivers/xen/xenbus/xenbus_xs.c | 40 +++++++++---------- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c index b758c9f676..cee8d74e8f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c @@ -137,6 +137,14 @@ int xb_write(const void *data, unsigned len) return 0; } +int xb_wait_for_data_to_read(void) +{ + struct xenstore_domain_interface *intf = xen_store_interface; + return wait_event_interruptible( + xb_waitq, + intf->rsp_cons != intf->rsp_prod); +} + int xb_read(void *data, unsigned len) { struct xenstore_domain_interface *intf = xen_store_interface; @@ -147,9 +155,7 @@ int xb_read(void *data, unsigned len) unsigned int avail; const char *src; - rc = wait_event_interruptible( - xb_waitq, - intf->rsp_cons != intf->rsp_prod); + rc = xb_wait_for_data_to_read(); if (rc < 0) return rc; diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h index b54d168cbb..95f10e1255 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h @@ -37,6 +37,7 @@ int xb_init_comms(void); /* Low level routines. */ int xb_write(const void *data, unsigned len); int xb_read(void *data, unsigned len); +int xb_wait_for_data_to_read(void); int xs_input_avail(void); extern struct xenstore_domain_interface *xen_store_interface; extern int xen_store_evtchn; diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c index 23b99b86f5..69a941d509 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c @@ -150,22 +150,6 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) return body; } -/* Emergency write. */ -void xenbus_debug_write(const char *str, unsigned int count) -{ - struct xsd_sockmsg msg = { 0 }; - - msg.type = XS_DEBUG; - msg.len = sizeof("print") + count + 1; - - mutex_lock(&xs_state.request_mutex); - xb_write(&msg, sizeof(msg)); - xb_write("print", sizeof("print")); - xb_write(str, count); - xb_write("", 1); - mutex_unlock(&xs_state.request_mutex); -} - void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) { void *ret; @@ -753,27 +737,38 @@ static int process_msg(void) char *body; int err; + err = xb_wait_for_data_to_read(); + if (err) + return err; + msg = kmalloc(sizeof(*msg), GFP_KERNEL); if (msg == NULL) return -ENOMEM; + /* + * We are now committed to reading an entire message. Partial reads + * across save/restore leave us out of sync with the xenstore daemon. + */ + down_read(&xs_state.suspend_mutex); + err = xb_read(&msg->hdr, sizeof(msg->hdr)); if (err) { kfree(msg); - return err; + goto out; } body = kmalloc(msg->hdr.len + 1, GFP_KERNEL); if (body == NULL) { kfree(msg); - return -ENOMEM; + err = -ENOMEM; + goto out; } err = xb_read(body, msg->hdr.len); if (err) { kfree(body); kfree(msg); - return err; + goto out; } body[msg->hdr.len] = '\0'; @@ -782,7 +777,8 @@ static int process_msg(void) &msg->u.watch.vec_size); if (IS_ERR(msg->u.watch.vec)) { kfree(msg); - return PTR_ERR(msg->u.watch.vec); + err = PTR_ERR(msg->u.watch.vec); + goto out; } spin_lock(&watches_lock); @@ -806,7 +802,9 @@ static int process_msg(void) wake_up(&xs_state.reply_waitq); } - return 0; + out: + up_read(&xs_state.suspend_mutex); + return err; } static int xenbus_thread(void *unused) -- 2.30.2